#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <map>
#include <set>
#include "mesh.h"
#include "simp.h"
/*
void simplification (Mesh & mesh, unsigned num_collapse) 
{
	mesh.prepare_simp_data();
	Heap heap; 
	for(EdgeIterator iter = mesh.edges.begin(); iter!=mesh.edges.end(); ++iter)
	{
		heap.insert(iter->second);
	}
	heap.print_heap();
}
*/
void simplification (Mesh & mesh, unsigned num_collapse) 
{
	
	mesh.prepare_simp_data(); 
	//mesh.print_vertex();
	Heap heap; 
	for(EdgeIterator iter = mesh.edges.begin(); iter!=mesh.edges.end(); ++iter)
	{
		heap.insert(iter->second);
	}
	//heap.print_heap(); 

	std::vector<Edge *> unsafe_edge ;
	unsigned count = 1; 
	while (!heap.empty())
	{
		
		if (count > num_collapse) break;
		Edge * edge = heap.pop();
		if (is_edge_safe(edge))
		{
			if (count % 10000 == 0) 
			{
					std::cout<<"Removed "<<count*2<<" faces."<<std::endl;
			}
			
			//std::cout<<"PASS "<<count<<std::endl;
			/*
			std::cout<<"HEAPSIZE "<<heap.size()<<std::endl;
			std::cout<<"UNSAFE SIZE "<<unsafe_edge.size()<<std::endl; 
			*/
			//std::cout<<"LEAST VALUE "<<edge->cost<<std::endl;
			//std::cout<<"Remove Edge"<<edge<<edge->he->next->edge<<' '<<edge->he->flip->prev->edge<< std::endl;
			

			for (std::vector<Edge * >::iterator iter = unsafe_edge.begin(); 
				iter != unsafe_edge.end(); ++iter)
			{
				heap.insert(*iter);
			}
			unsafe_edge.clear();
			
			count ++ ;
			heap.remove(edgeHashKey(edge->he->next->edge));
			heap.remove(edgeHashKey(edge->he->flip->prev->edge));

			unsigned id_old ;
			unsigned id_new;
			std::vector<unsigned> neighbor;
			mesh.edge_collapse(edge, id_old, id_new, neighbor);
			//Modify heap structure
			for (unsigned i = 0; i < neighbor.size(); ++i)
			{
				heap.remove(edgeHashKey(id_old, neighbor[i]));
				Edge * newedge = mesh.edges[edgeHashKey(id_new, neighbor[i])];
				//mesh.evaluate_edge_cost(newedge);
				heap.insert(newedge);
			}
			
			//Update the cost in heap
			
			Vertex * v = (edge->he->from_v);
			HalfEdge * iter = v->edge ;
			HalfEdge * end = iter;
			do 
			{
				//mesh.evaluate_edge_cost(iter->edge);
				heap.update(iter->edge);
				iter= iter->flip->next; 
			} while (iter != end);
			
		}
		else
		{
			unsafe_edge.push_back(edge); 
		}
		//std::cout<<"Removed "<<num_collapse * 2<<std::endl;
	}
	
	
	/*
	unsigned count = 0;
	while (count <= num_collapse)
	{
		std::cout<<"PASS "<<count<<std::endl;
		
		if (!mesh.is_valid_mesh())
		{
			std::cout<<"INVALID MESH"<<std::endl;
			break;
		}
		
		count++;
		//mesh.print_edges();
		stdext::hash_map <EdgeHashKey, Edge * >::iterator iter = mesh.edges.begin();
		while (! is_edge_safe(iter->second))
		{
			++iter ;
			//std::cout<<"Hello2"<<std::endl;
		}
		mesh.edge_collapse(iter->second);
		
	}
	
	*/
}